import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:website.core/core/domain/entities/app_store/app_store_one_time_purchased_item.dart';
import 'package:website.core/core/domain/entities/app_store/app_store_purchased_item.dart';
import 'package:website.core/core/domain/entities/app_store/app_store_purchased_subscription.dart';
import 'package:website.core/core/domain/entities/app_store/app_store_purchased_subscription_status.dart';
import 'package:website.core/core/domain/entities/google_play/google_play_one_time_purchased_item.dart';
import 'package:website.core/core/domain/entities/google_play/google_play_purchased_item.dart';
import 'package:website.core/core/domain/entities/google_play/google_play_purchased_subscription.dart';
import 'package:website.core/core/domain/entities/google_play/google_play_purchased_subscription_status.dart';
import 'package:website.core/core/domain/entities/web/web_one_time_purchased_item.dart';
import 'package:website.core/core/domain/entities/web/web_purchase_item.dart';
import 'package:website.core/core/domain/entities/web/web_purchased_item.dart';
import 'package:website.core/core/domain/entities/web/web_purchased_subscription.dart';
import 'package:website.core/core/domain/entities/web/web_purchased_subscription_status.dart';
import 'package:website.core/core/domain/helpers/prettify_web_purchase_item_prices/prettify_web_purchase_item_prices.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/app_store_one_time_purchased_item_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/app_store_purchased_subscription_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/google_play_one_time_purchased_item_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/google_play_purchased_subscription_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/one_time_purchased_item_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/purchased_item_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/purchased_subscription_duration.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/purchased_subscription_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/web_one_time_purchased_item_model.dart';
import 'package:website.home.account/purchase_management_fragment/domain/entites/web_purchased_subscription_model.dart';

part 'result.dart';

const _kMonthSubscriptionSkus = {
  'com.meowofficial.words.month',
  'com.meowofficial.words.2.month',
  'com.meowofficial.words.3.month.trial',
  'com.meowofficial.words.3.month',
};

const _kQuarterSubscriptionSkus = {
  'com.meowofficial.words.quarter',
};

const _kYearSubscriptionSkus = {
  'com.meowofficial.words.year',
  'com.meowofficial.words.year.introduction',
  'com.meowofficial.words.3.year.trial',
  'com.meowofficial.words.3.year',
};

abstract class CreatePurchasedItemModels {
  PurchasedItemModelCreationResult call({
    required BuiltList<AppStorePurchasedItem> appStorePurchasedItems,
    required BuiltList<GooglePlayPurchasedItem> googlePlayPurchasedItems,
    required BuiltList<WebPurchasedItem> webPurchasedItems,
    required BuiltMap<String, WebPurchaseItem> webPurchaseItemMap,
  });
}

class CreatePurchasedItemModelsImpl implements CreatePurchasedItemModels {
  const CreatePurchasedItemModelsImpl({
    required PrettifyWebPurchaseItemPrices prettifyWebPurchaseItemPrices,
  }) : _prettifyWebPurchaseItemPrices = prettifyWebPurchaseItemPrices;

  final PrettifyWebPurchaseItemPrices _prettifyWebPurchaseItemPrices;

  @override
  PurchasedItemModelCreationResult call({
    required BuiltList<AppStorePurchasedItem> appStorePurchasedItems,
    required BuiltList<GooglePlayPurchasedItem> googlePlayPurchasedItems,
    required BuiltList<WebPurchasedItem> webPurchasedItems,
    required BuiltMap<String, WebPurchaseItem> webPurchaseItemMap,
  }) {
    final activePurchasedItemModels = <PurchasedItemModel>[];
    final pausedGooglePlayPurchasedSubscriptionModels = <GooglePlayPurchasedSubscriptionModel>[];
    final expiredPurchasedSubscriptionModels = <PurchasedSubscriptionModel>[];

    for (final appStorePurchasedItem in appStorePurchasedItems) {
      if (appStorePurchasedItem is AppStoreOneTimePurchasedItem) {
        final appStoreOneTimePurchasedItem = appStorePurchasedItem;

        if (!appStoreOneTimePurchasedItem.revoked) {
          final appStoreOneTimePurchasedItemModel = AppStoreOneTimePurchasedItemModel(
            purchaseItemSku: appStoreOneTimePurchasedItem.purchaseItemSku,
            transactionId: appStoreOneTimePurchasedItem.transactionId,
            revoked: appStoreOneTimePurchasedItem.revoked,
          );

          activePurchasedItemModels.add(appStoreOneTimePurchasedItemModel);
        }
      } else if (appStorePurchasedItem is AppStorePurchasedSubscription) {
        final appStorePurchasedSubscription = appStorePurchasedItem;

        final duration = _getPurchasedSubscriptionDurationBySku(
          purchaseSubscriptionSku: appStorePurchasedSubscription.purchaseItemSku,
        );

        final status = appStorePurchasedSubscription.status;

        final appStorePurchasedSubscriptionItemModel = AppStorePurchasedSubscriptionModel(
          purchaseItemSku: appStorePurchasedSubscription.purchaseItemSku,
          originalTransactionId: appStorePurchasedSubscription.originalTransactionId,
          status: status,
          autoRenewalEnabled: appStorePurchasedSubscription.autoRenewalEnabled,
          expirationTime: appStorePurchasedSubscription.expirationTime,
          gracePeriodExpirationTime: appStorePurchasedSubscription.gracePeriodExpirationTime,
          duration: duration,
        );

        if (status == AppStorePurchasedSubscriptionStatus.active ||
            status == AppStorePurchasedSubscriptionStatus.inGracePeriod) {
          activePurchasedItemModels.add(appStorePurchasedSubscriptionItemModel);
        } else if (status == AppStorePurchasedSubscriptionStatus.expired ||
            status == AppStorePurchasedSubscriptionStatus.inBillingRetryPeriod) {
          expiredPurchasedSubscriptionModels.add(appStorePurchasedSubscriptionItemModel);
        }
      }
    }

    for (final googlePlayPurchasedItem in googlePlayPurchasedItems) {
      if (googlePlayPurchasedItem is GooglePlayOneTimePurchasedItem) {
        final googlePlayOneTimePurchasedItem = googlePlayPurchasedItem;

        if (!googlePlayOneTimePurchasedItem.revoked) {
          final googlePlayOneTimePurchasedItemModel = GooglePlayOneTimePurchasedItemModel(
            purchaseItemSku: googlePlayOneTimePurchasedItem.purchaseItemSku,
            purchaseToken: googlePlayOneTimePurchasedItem.purchaseToken,
            revoked: googlePlayOneTimePurchasedItem.revoked,
          );

          activePurchasedItemModels.add(googlePlayOneTimePurchasedItemModel);
        }
      } else if (googlePlayPurchasedItem is GooglePlayPurchasedSubscription) {
        final googlePlayPurchasedSubscription = googlePlayPurchasedItem;

        final duration = _getPurchasedSubscriptionDurationBySku(
          purchaseSubscriptionSku: googlePlayPurchasedSubscription.purchaseItemSku,
        );

        final status = googlePlayPurchasedSubscription.status;

        final googlePlayPurchasedSubscriptionItemModel = GooglePlayPurchasedSubscriptionModel(
          purchaseItemSku: googlePlayPurchasedSubscription.purchaseItemSku,
          purchaseToken: googlePlayPurchasedSubscription.purchaseToken,
          status: status,
          autoRenewalEnabled: googlePlayPurchasedSubscription.autoRenewalEnabled,
          expirationTime: googlePlayPurchasedSubscription.expirationTime,
          pauseInfo: googlePlayPurchasedSubscription.pauseInfo,
          duration: duration,
        );

        if (status == GooglePlayPurchasedSubscriptionStatus.active) {
          activePurchasedItemModels.add(googlePlayPurchasedSubscriptionItemModel);
        } else if (status == GooglePlayPurchasedSubscriptionStatus.paused) {
          pausedGooglePlayPurchasedSubscriptionModels.add(googlePlayPurchasedSubscriptionItemModel);
        } else if (status == GooglePlayPurchasedSubscriptionStatus.expired) {
          expiredPurchasedSubscriptionModels.add(googlePlayPurchasedSubscriptionItemModel);
        }
      }
    }

    for (final webPurchasedItem in webPurchasedItems) {
      final webPurchaseItem = webPurchaseItemMap[webPurchasedItem.purchaseItemSku]!;

      final pretifiedPrices = _prettifyWebPurchaseItemPrices(
        prices: BuiltList([
          webPurchaseItem.price,
        ]),
      );

      final pretifiedPrice = pretifiedPrices.first;

      if (webPurchasedItem is WebOneTimePurchasedItem) {
        final webOneTimePurchasedItem = webPurchasedItem;

        if (!webOneTimePurchasedItem.revoked) {
          final webOneTimePurchasedItemModel = WebOneTimePurchasedItemModel(
            purchaseItemSku: webOneTimePurchasedItem.purchaseItemSku,
            transactionId: webOneTimePurchasedItem.transactionId,
            revoked: webOneTimePurchasedItem.revoked,
            pretifiedPrice: pretifiedPrice,
            currency: webPurchaseItem.price.currency,
          );

          activePurchasedItemModels.add(webOneTimePurchasedItemModel);
        }
      } else if (webPurchasedItem is WebPurchasedSubscription) {
        final webPurchasedSubscription = webPurchasedItem;

        final duration = _getPurchasedSubscriptionDurationBySku(
          purchaseSubscriptionSku: webPurchasedSubscription.purchaseItemSku,
        );

        final status = webPurchasedSubscription.status;

        final webPurchasedSubscriptionItemModel = WebPurchasedSubscriptionModel(
          purchaseItemSku: webPurchasedSubscription.purchaseItemSku,
          originalTransactionId: webPurchasedSubscription.originalTransactionId,
          status: status,
          autoRenewalEnabled: webPurchasedSubscription.autoRenewalEnabled,
          expirationTime: webPurchasedSubscription.expirationTime,
          duration: duration,
          pretifiedPrice: pretifiedPrice,
          currency: webPurchaseItem.price.currency,
        );

        if (status == WebPurchasedSubscriptionStatus.active) {
          activePurchasedItemModels.add(webPurchasedSubscriptionItemModel);
        } else if (status == WebPurchasedSubscriptionStatus.expired) {
          expiredPurchasedSubscriptionModels.add(webPurchasedSubscriptionItemModel);
        }
      }
    }

    _sortActivePurchasedItemModels(activePurchasedItemModels);
    _sortPausedGooglePlayPurchasedSubscriptionModels(pausedGooglePlayPurchasedSubscriptionModels);
    _sortExpiredPurchasedSubscriptionModels(expiredPurchasedSubscriptionModels);

    final result = PurchasedItemModelCreationResult(
      activePurchasedItemModels: activePurchasedItemModels.toBuiltList(),
      pausedGooglePlayPurchasedSubscriptionModels:
          pausedGooglePlayPurchasedSubscriptionModels.toBuiltList(),
      expiredPurchasedSubscriptionModels: expiredPurchasedSubscriptionModels.toBuiltList(),
    );

    return result;
  }

  PurchasedSubscriptionDuration _getPurchasedSubscriptionDurationBySku({
    required String purchaseSubscriptionSku,
  }) {
    if (_kMonthSubscriptionSkus.contains(purchaseSubscriptionSku)) {
      return PurchasedSubscriptionDuration.month;
    }

    if (_kQuarterSubscriptionSkus.contains(purchaseSubscriptionSku)) {
      return PurchasedSubscriptionDuration.quarter;
    }

    if (_kYearSubscriptionSkus.contains(purchaseSubscriptionSku)) {
      return PurchasedSubscriptionDuration.year;
    }

    throw UnimplementedError();
  }

  void _sortActivePurchasedItemModels(List<PurchasedItemModel> activePurchasedItemModels) {
    int getOneTimePurchasedItemModelSourcePriority(
        OneTimePurchasedItemModel oneTimePurchasedItemModel) {
      if (oneTimePurchasedItemModel is WebOneTimePurchasedItemModel) {
        return 0;
      }

      if (oneTimePurchasedItemModel is AppStoreOneTimePurchasedItemModel) {
        return 1;
      }

      if (oneTimePurchasedItemModel is GooglePlayOneTimePurchasedItemModel) {
        return 2;
      }

      throw UnimplementedError();
    }

    int getPurchasedItemModelTypePriority(PurchasedItemModel purchasedItemModel) {
      if (purchasedItemModel is PurchasedSubscriptionModel) {
        return 0;
      }

      if (purchasedItemModel is OneTimePurchasedItemModel) {
        return 1;
      }

      throw UnimplementedError();
    }

    activePurchasedItemModels.sort((first, second) {
      final firstTypePriority = getPurchasedItemModelTypePriority(first);
      final secondTypePriority = getPurchasedItemModelTypePriority(second);

      if (firstTypePriority != secondTypePriority) {
        return firstTypePriority.compareTo(secondTypePriority);
      }

      if (first is OneTimePurchasedItemModel && second is OneTimePurchasedItemModel) {
        final firstSourcePriority = getOneTimePurchasedItemModelSourcePriority(first);
        final secondSourcePriority = getOneTimePurchasedItemModelSourcePriority(second);

        return firstSourcePriority.compareTo(secondSourcePriority);
      }

      if (first is PurchasedSubscriptionModel && second is PurchasedSubscriptionModel) {
        final firstExpirationTime = first.expirationTime!;
        final secondExpirationTime = second.expirationTime!;

        return firstExpirationTime.compareTo(secondExpirationTime);
      }

      throw UnimplementedError();
    });
  }

  void _sortPausedGooglePlayPurchasedSubscriptionModels(
      List<GooglePlayPurchasedSubscriptionModel> pausedGooglePlayPurchasedSubscriptionModels) {
    pausedGooglePlayPurchasedSubscriptionModels.sort((first, second) {
      final firstAutoResumeTime = first.pauseInfo!.autoResumeTime;
      final secondAutoResumeTime = second.pauseInfo!.autoResumeTime;

      return firstAutoResumeTime.compareTo(secondAutoResumeTime);
    });
  }

  void _sortExpiredPurchasedSubscriptionModels(
      List<PurchasedSubscriptionModel> expiredPurchasedSubscriptionModels) {
    expiredPurchasedSubscriptionModels.sort((first, second) {
      final firstExpirationTime = first.expirationTime!;
      final secondExpirationTime = second.expirationTime!;

      return firstExpirationTime.compareTo(secondExpirationTime);
    });
  }
}
